#ifndef _AwQuaternion
#define _AwQuaternion
//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors, which is protected by U.S. and Canadian federal copyright 
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right 
// to use, modify, and incorporate this Data into other products for 
// purposes authorized by the Autodesk software license agreement, 
// without fee.
//
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the 
// following disclaimer, must be included in all copies of the 
// Software, in whole or in part, and all derivative works of 
// the Software, unless such copies or derivative works are solely 
// in the form of machine-executable object code generated by a 
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+
//
//	CLASS:    AwQuaternion
//
// *****************************************************************************
//
//	CLASS DESCRIPTION (AwQuaternion)
//
//	Quaternions can be used to specify orientations and rotations of 3-D
//	objects relative to a starting reference, similar to the way that cartesian
//	vectors can be used to specify positions and translations of 3-D objects
//	relative to an origin.  Quaternions represent orientations as a single
//	rotation, just as rectangular co-ordinates represent position as a single
//	vector.
//
// *****************************************************************************

#include <AwMath.h>
#include <MIOStream.h>

class AwVector;
class AwMatrix;

class AwQuaternion {
public:
	//	Constructors
	//
	AwQuaternion(); 
	AwQuaternion(const AwQuaternion &q); 
	AwQuaternion(double x, double y, double z, double w); 
	AwQuaternion(const AwVector &, const AwVector &); 
	AwQuaternion(double angle, const AwVector &axis); 
#ifndef COMPILE_OUTSIDE_MAYA
	AwQuaternion(const MQuaternion &q);
	operator MQuaternion() const;
#endif
	~AwQuaternion(); 

	AwQuaternion &operator=(const AwQuaternion &); 
	AwQuaternion &operator=(const AwMatrix &);

	double &operator[](unsigned i); 
	double  operator[](unsigned i) const; 

	AwQuaternion operator*(const AwQuaternion &) const; 

	bool operator==(const AwQuaternion &) const; 
	bool operator!=(const AwQuaternion &) const; 

	operator AwMatrix() const;
	void convertToMatrix(AwMatrix &) const;

	AwQuaternion &setAxisAngle(const AwVector &axis, double theta); 
	bool getAxisAngle(AwVector &axis, double &theta) const; 
	
    friend ostream &operator<<(ostream &os, const AwQuaternion &);

    static const AwQuaternion identity; // The multiplicative identity. 

	double x, y, z, w; // imaginary (3) & real components
};

///////////////////////////////////////////////////////////////////////////
//	Inline methods
///////////////////////////////////////////////////////////////////////////

inline AwQuaternion::AwQuaternion()
: w(1.0), x(0.0), y(0.0), z(0.0)
{}

inline AwQuaternion::AwQuaternion(const AwQuaternion &q)
: w(q.w), x(q.x), y(q.y), z(q.z)
{}

inline AwQuaternion::AwQuaternion(double a, double b, double c, double d)
: x(a), y(b), z(c), w(d)
{}

inline AwQuaternion::AwQuaternion(double angle, const AwVector &axis)
: w(1.0), x(0.0), y(0.0), z(0.0)
{ setAxisAngle(axis, angle); }

#ifndef COMPILE_OUTSIDE_MAYA
inline AwQuaternion::AwQuaternion(const MQuaternion &q)
: w(q.w), x(q.x), y(q.y), z(q.z)
{}

inline AwQuaternion::operator MQuaternion() const
{
	return MQuaternion(x, y, z, w);
}
#endif

inline AwQuaternion::~AwQuaternion ()
{}

inline AwQuaternion &AwQuaternion::operator=(const AwQuaternion &src)
{ w = src.w; x = src.x; y = src.y; z = src.z; return *this; }

inline double &AwQuaternion::operator[](unsigned i)
{ return (&x)[i]; }

inline double AwQuaternion::operator[](unsigned i) const
{ return (&x)[i]; }

inline bool AwQuaternion::operator==( const AwQuaternion &otherQ ) const
{ return w == otherQ.w && x == otherQ.x && y == otherQ.y && z == otherQ.z; }

inline bool AwQuaternion::operator!=( const AwQuaternion &otherQ ) const
{ return !( (*this) == otherQ ); }

#endif /* _AwQuaternion */
